/**
 * MP Software.
 */
package service;

import helpers.ElectronicIdConstant;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import models.Deduction;
import models.Payment;
import models.Payroll;

import org.apache.commons.lang.math.NumberUtils;

import service.calculator.DeductionType;
import service.calculator.PaymentType;
import service.calculator.aristocrat.AristocratDeductionType;
import service.calculator.aristocrat.AristocratPaymentType;
import service.calculator.bagnetified.sanmateo.BagnetifiedSanMateoDeductionType;
import service.calculator.bagnetified.sanmateo.BagnetifiedSanMateoPaymentType;
import service.calculator.bonchon.BonchonDeductionType;
import service.calculator.bonchon.BonchonPaymentType;
import service.calculator.crystalite.CrystaliteDeductionType;
import service.calculator.crystalite.CrystalitePaymentType;
import service.calculator.jeron.JeronDeductionType;
import service.calculator.jeron.JeronPaymentType;
import service.calculator.sonic.SonicDeductionType;
import service.calculator.sonic.SonicPaymentType;
import controllers.views.DeductionTypeView;
import controllers.views.PaymentTypeView;

/**
 * @author Jeremiah John M. Macariola
 * 
 */
public class PaymentDeductionFacadeImpl implements PaymentDeductionFacade {

	public List<PaymentTypeView> getPaymentTypes(String electronicId) {
		List<PaymentTypeView> paymentTypeViews = new ArrayList<PaymentTypeView>();

		List<PaymentType> paymentTypes = switchPaymentTypes(electronicId);
		for (PaymentType pt : paymentTypes) {
			paymentTypeViews.add(new PaymentTypeView(pt.getName(), pt
					.getLabel(), pt.getDescription()));
		}

		return paymentTypeViews;
	}

	public List<DeductionTypeView> getDeductionTypes(String electronicId) {
		List<DeductionTypeView> deductionTypeViews = new ArrayList<DeductionTypeView>();

		List<DeductionType> deductionTypes = switchDeductionTypes(electronicId);
		for (DeductionType dt : deductionTypes) {
			deductionTypeViews.add(new DeductionTypeView(dt.getName(), dt
					.getLabel(), dt.getDescription()));
		}

		return deductionTypeViews;
	}

	public void savePayments(String electronicId, Payroll payroll,
			Map<String, String> paymentDeductionParams) {
		List<PaymentType> paymentTypes = switchPaymentTypes(electronicId);
		for (PaymentType pt : paymentTypes) {
			String typeName = pt.getName();
			String value = paymentDeductionParams.get(typeName);
			Payment payment = Payment.find("byPaymentTypeAndPayroll", typeName,
					payroll).first();
			boolean hasValue = NumberUtils.isNumber(value);
			if (payment != null) {
				if (hasValue) {
					payment.hours = Float.valueOf(value);
					payment.save();
				} else {
					payment.delete();
				}

			} else if (hasValue) {
				payment = new Payment(typeName, Float.valueOf(value), payroll);
				payment.save();
			}
		}
	}

	public void saveDeductions(String electronicId, Payroll payroll,
			Map<String, String> paymentDeductionParams) {
		List<DeductionType> deductionTypes = switchDeductionTypes(electronicId);
		for (DeductionType dt : deductionTypes) {
			String typeName = dt.getName();
			String value = paymentDeductionParams.get(typeName);
			Deduction deduction = Deduction.find("byDeductionTypeAndPayroll",
					typeName, payroll).first();
			boolean hasValue = NumberUtils.isNumber(value);
			if (deduction != null) {
				if (hasValue) {
					deduction.value = new BigDecimal(value);
					deduction.save();
				} else {
					deduction.delete();
				}

			} else if (hasValue) {
				deduction = new Deduction(typeName, new BigDecimal(value),
						payroll);
				deduction.save();
			}
		}
	}

	public boolean hasValue(String electronicId,
			Map<String, String> paymentDeductionParams) {
		List<PaymentType> paymentTypes = switchPaymentTypes(electronicId);
		for (PaymentType pt : paymentTypes) {
			String value = paymentDeductionParams.get(pt.getName());
			if (NumberUtils.isNumber(value)) {
				return true;
			}
		}

		List<DeductionType> deductionTypes = switchDeductionTypes(electronicId);
		for (DeductionType dt : deductionTypes) {
			String value = paymentDeductionParams.get(dt.getName());
			if (NumberUtils.isNumber(value)) {
				return true;
			}
		}

		return false;
	}

	private List<PaymentType> switchPaymentTypes(String electronicId) {
		List<PaymentType> paymentTypes = null;

		if (ElectronicIdConstant.BONCHON.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_BATANGAS.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_PASEO.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_BAGUIO.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_MARQUEE.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_LUMINA.equals(electronicId)) {
			List<BonchonPaymentType> types = Arrays.asList(BonchonPaymentType
					.values());
			paymentTypes = new ArrayList<PaymentType>(types);

		} else if (ElectronicIdConstant.ARISTOCRAT.equals(electronicId)) {
			List<AristocratPaymentType> types = Arrays
					.asList(AristocratPaymentType.values());
			paymentTypes = new ArrayList<PaymentType>(types);

		} else if (ElectronicIdConstant.CRYSTALITE.equals(electronicId)
				|| ElectronicIdConstant.CRYSTALITE_LAGUNA.equals(electronicId)) {
			List<CrystalitePaymentType> types = Arrays
					.asList(CrystalitePaymentType.values());
			paymentTypes = new ArrayList<PaymentType>(types);
		} else if (ElectronicIdConstant.JERON.equals(electronicId)) {
			List<JeronPaymentType> types = Arrays
					.asList(JeronPaymentType.values());
			paymentTypes = new ArrayList<PaymentType>(types);
		} else if (ElectronicIdConstant.SONIC.equals(electronicId)
				|| ElectronicIdConstant.SONIC_2.equals(electronicId)) {
			List<SonicPaymentType> types = Arrays
				.asList(SonicPaymentType.values());
			paymentTypes = new ArrayList<PaymentType>(types);
		} else if (ElectronicIdConstant.BAGNETIFIED_SANMATEO.equals(electronicId)) {
			List<BagnetifiedSanMateoPaymentType> types = Arrays
					.asList(BagnetifiedSanMateoPaymentType.values());
			paymentTypes = new ArrayList<PaymentType>(types);
		}

		return paymentTypes;
	}

	private List<DeductionType> switchDeductionTypes(String electronicId) {
		List<DeductionType> deductionTypes = null;

		if (ElectronicIdConstant.BONCHON.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_BATANGAS.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_PASEO.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_BAGUIO.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_MARQUEE.equals(electronicId)
				|| ElectronicIdConstant.BONCHON_LUMINA.equals(electronicId)) {
			List<BonchonDeductionType> types = Arrays
					.asList(BonchonDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);

		} else if (ElectronicIdConstant.ARISTOCRAT.equals(electronicId)) {
			List<AristocratDeductionType> types = Arrays
					.asList(AristocratDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);

		} else if (ElectronicIdConstant.CRYSTALITE.equals(electronicId)
				|| ElectronicIdConstant.CRYSTALITE_LAGUNA.equals(electronicId)) {
			List<CrystaliteDeductionType> types = Arrays
					.asList(CrystaliteDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);
		} else if (ElectronicIdConstant.JERON.equals(electronicId)) {
			List<JeronDeductionType> types = Arrays
					.asList(JeronDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);
		} else if (ElectronicIdConstant.SONIC.equals(electronicId)
				|| ElectronicIdConstant.SONIC_2.equals(electronicId)) {
			List<SonicDeductionType> types = Arrays
				.asList(SonicDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);
		} else if (ElectronicIdConstant.BAGNETIFIED_SANMATEO.equals(electronicId)) {
			List<BagnetifiedSanMateoDeductionType> types = Arrays
					.asList(BagnetifiedSanMateoDeductionType.values());
			deductionTypes = new ArrayList<DeductionType>(types);
		}

		return deductionTypes;
	}

}
